package ro.peoplecentric.ctc.common.aop;

import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionException;

import ro.peoplecentric.ctc.common.exception.ApplicationException;
import ro.peoplecentric.ctc.common.exception.DataBaseException;

/**
 * TransactionAspect catches and translate the DAO and transactions exceptions.
 *
 * @author pguzun
 */
@Component
@Aspect
@Order(1)
public class TransactionAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(TransactionAspect.class);

    @Pointcut("execution(* ro.peoplecentric.ctc.common.service..*.*(..)) && @target(org.springframework.transaction.annotation.Transactional)")
    public void applyTransactionAspect() {
    }

    /**
     * If transaction can't be created or flushed (normally the DB is down) this exception is catch here.
     *
     * @param ex
     * @throws ApplicationException
     */
    @AfterThrowing(pointcut = "applyTransactionAspect()", throwing = "ex")
    public void afterThrowTransaction(java.lang.RuntimeException ex) throws ApplicationException {
        if (ex instanceof TransactionException) {
            ApplicationException e = new DataBaseException(ex);
            LOGGER.error(e.getMessage(), e);
            throw e;
        } else if (ex instanceof DataAccessException) {
            ApplicationException e = new DataBaseException(ex);
            LOGGER.error(e.getMessage(), e);
            throw e;
        }
        throw ex;
    }
}
